package com.sojson.config;

import java.util.HashMap;

import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;

import com.sojson.config.exception.TransException;
import com.sojson.constant.Constant;
import com.sojson.constant.ConstantByMap;
import com.sojson.util.servlet.ServletUtil;
import com.sojson.util.text.Convert;

/**
 * 错误页面bean
 * 
 * @author liu
 * @date 2020-11-02
 */
@Configuration
public class ErrorPageConfig {

    /** 所有系统异常的集合 */
    public static final HashMap<String, TransException> TRANS_ERROR_CODE = new HashMap<>();

    /** 返回本地页面 */
    private static final int RESPONSE_DATA_TYPE_PAGE = 1;
    /** 返回远程页面 */
    private static final int RESPONSE_DATA_TYPE_LONG_PAGE = 2;
    /** 返回Json数据 */
    private static final int RESPONSE_DATA_TYPE_JSON = 3;
    /** 系统错误返回页面还是返回数据(1.返回本地页面,2.返回远程页面,3.返回Json数据),不设置为返回本地页面 */
    private static int RESPONSE_DATA_TYPE = Convert
        .toInt(Constant.PROPERTIES.getProperty("so.application.error.responseData.type"), RESPONSE_DATA_TYPE_PAGE);
    /** 错误页面的Controller路径(模糊路径) */
    private static final String ERROR_PAGE_URL = getErrorController();
    /** 错误页面的Controller全路径(模糊路径) */
    public static final String ERROR_PAGE_URL_ALL = ServletUtil.getMappingUrl(ERROR_PAGE_URL);

    /**
     * SpringBoot2.0以上版本
     *
     * @return
     */
    @Bean
    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
        // 第二种写法：java8 lambda写法
        return (factory -> {
            // TODO

            ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, getErrorPageUrl("404"));
            factory.addErrorPages(errorPage404);
            ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, getErrorPageUrl("500"));
            factory.addErrorPages(errorPage500);

        });

        // // 第一种：java7 常规写法
        // return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
        // @Override
        // publi void customize(ConfigurableWebServerFactory factory) {
        // ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
        // factory.addErrorPages(errorPage404);
        // }
        // };

    }

    /**
     * 获取错误页面Controller
     * 匿名内部类和局部内部类只能引用外部的final变量,如果当着内部类的面修改变量,它会觉得这不是final变量,然后编译不通过
     * 
     * @return
     */
    private static String getErrorController() {
        if (RESPONSE_DATA_TYPE_PAGE == RESPONSE_DATA_TYPE) {
            return ConstantByMap.CONTROLLER_MAPPING_OPEN_OPEN + "/error" + "/page";
        } else if (RESPONSE_DATA_TYPE_LONG_PAGE == RESPONSE_DATA_TYPE) {
            return ConstantByMap.CONTROLLER_MAPPING_OPEN_OPEN + "/error" + "/page/longPage";
        } else if (RESPONSE_DATA_TYPE_JSON == RESPONSE_DATA_TYPE) {
            // TODO

            // 2xx 成功
            TRANS_ERROR_CODE.put("200", new TransException(200, "请求已完成。"));
            TRANS_ERROR_CODE.put("202", new TransException(202, "已接受用于处理，但处理尚未完成。"));
            TRANS_ERROR_CODE.put("203", new TransException(203, "部分信息 — 返回的信息只是一部分。"));
            TRANS_ERROR_CODE.put("204", new TransException(204, "无响应 — 已接收请求，但不存在要回送的信息。"));

            // 4xx 客户机中出现的错误
            TRANS_ERROR_CODE.put("400", new TransException(400, "错误请求 — 请求中有语法问题，或不能满足请求。"));
            TRANS_ERROR_CODE.put("401", new TransException(401, "未授权 — 未授权客户机访问数据。"));
            TRANS_ERROR_CODE.put("402", new TransException(402, "需要付款 — 表示计费系统已有效。"));
            TRANS_ERROR_CODE.put("403", new TransException(403, "禁止 — 即使有授权也不需要访问。"));
            TRANS_ERROR_CODE.put("404", new TransException(404, "找不到 — 服务器找不到给定的资源,文档不存在。"));
            TRANS_ERROR_CODE.put("405", new TransException(405, "请确认请求方式是否正确！Get？Post？..."));
            TRANS_ERROR_CODE.put("414", new TransException(414, "请求 - URI 太长。"));
            TRANS_ERROR_CODE.put("415", new TransException(415, "介质类型不受支持 — 服务器拒绝服务请求，因为不支持请求实体的格式。"));

            // 5xx 服务器中出现的错误
            TRANS_ERROR_CODE.put("500", new TransException(500, "内部错误 — 因为意外情况，服务器不能完成请求。"));
            TRANS_ERROR_CODE.put("501", new TransException(501, "未执行 — 服务器不支持请求的工具。"));
            TRANS_ERROR_CODE.put("502", new TransException(502, "错误网关 — 服务器接收到来自上游服务器的无效响应。"));
            TRANS_ERROR_CODE.put("503", new TransException(503, "无法获得服务 — 由于临时过载或维护，服务器无法处理请求。"));

            return ConstantByMap.CONTROLLER_MAPPING_OPEN_OPEN + "/error" + "/json";
        }
        return "";
    }

    // /**
    // * SpringBoot2.0之前版本
    // *
    // * @return
    // */
    // @Bean
    // public EmbeddedServletContainerCustomizer containerCustomizer() {
    // return new EmbeddedServletContainerCustomizer() {
    // @Override
    // public void customize(ConfigurableEmbeddedServletContainer container) {
    // ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "404.html");
    // container.addErrorPages(errorPage404);
    // }
    // };
    // }

    /**
     * 获取错误页面路径
     * 
     * @param code
     * @return
     */
    public static String getErrorPageUrl(String code) {
        return ERROR_PAGE_URL_ALL + "/" + code;
    }

}